package retrievedatafromrevishapi;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;

import bookworm.BookHistoryData;

import xmlextract.GetTagContent;

public class GetBookReadingHistoryFromAPI implements InterfaceGetReadingHistoryData
{
	
	
	
	/**
	 * powered by revish's API.
	 * based on a user name, it gets his/ her reading history and converts it into
	 * book reading data, where each book history data contains start date and finish date
	 * of a certain book.
	 * @param userName the user name whom we extract the reading history.
	 *  
	 * @return list of book history data(each for a specific book)
	 */
	public LinkedList<BookHistoryData> getReadingHistoryOfAUser(String userName)
	{
		String xmlOfReadingHistory = this.getXMLWithReadingHistory(userName);
		LinkedList<String> xmlWithHistoryOfEachBook =
				this.getXmlFromEachBook(xmlOfReadingHistory);
		LinkedList<BookHistoryData> booksHistoryData = new LinkedList<BookHistoryData>();
		for(int i = 0; i < xmlWithHistoryOfEachBook.size(); i++)
		{
			String xmlWithHistoryOfABook = xmlWithHistoryOfEachBook.get(i);
			BookHistoryData aBookHistoryData = this.getBookHistoryFromXML(xmlWithHistoryOfABook);
			booksHistoryData.add(aBookHistoryData);
		}
		
		return booksHistoryData;
		
		
	}
	
	
	@Override
	public int getNumberOfBooksInReadingHistoryOfAUser(String userName) 
	{
		String xmlOfReadingHistory = this.getXMLWithReadingHistory(userName);
		GetTagContent getContentFromXML = new GetTagContent();
		String booksInHistory =getContentFromXML.getTagContent(xmlOfReadingHistory, "totalbooks");
		if(booksInHistory.length() > 0)
		{
			return Integer.valueOf(booksInHistory);
		}
		else
		{
			return 0;
		}
	}
	
	/**
	 * it simply will request Revish's API to get a XML of Reading History from a user.
	 * @param userName name of user who we wish to extract his/ her reading history
	 * @return XML String with reading history data of a user.
	 */
	private String getXMLWithReadingHistory(String userName)
	{
		userName = GetBookReadingHistoryFromAPI.reformatUsernameToQuery(userName);
		String urlRequest = 
				"http://api.revish.com/getReadingHistory?apikey=5828ca0b04ec8f0ff84e81b184424d1a&limit=300&user=" + userName;
		//now, let's request Revish for book reviews
		try
		{
			URL resource = new URL(urlRequest);
			HttpURLConnection connection = (HttpURLConnection) resource.openConnection();
			connection.setRequestMethod("GET");
			connection.setDoOutput(true);
			connection.connect();
			InputStream inputStream = connection.getInputStream();
			Reader streamReader = new InputStreamReader(inputStream);
			BufferedReader buffer = new BufferedReader(streamReader);
			String readLine = buffer.readLine();
			String xml = "";
			while(readLine != null)
			{
				xml = xml + readLine;
				readLine = buffer.readLine();
			}
			connection.disconnect();
			return xml;
		}
		catch(MalformedURLException exc)
		{
			return null;
		}
		catch(IOException exc)
		{
			System.out.println(exc);
			System.out.println("connection problems. Retrying to obtain xml...");
			return this.getXMLWithReadingHistory(userName);
		}
	}
	
	
	/**
	 * it splits the XML given as parameter of function into separate XML Strings, each
	 * representing a single book history data.
	 * @param XMLWithBooksFromHistory XML(not separated) with a lot of Book History Data
	 * in which me wish to split into single Book History Data XML.
	 * @return list with XML with each element in list referring to a single book history
	 * data.
	 */
	private LinkedList<String> getXmlFromEachBook(String XMLWithBooksFromHistory)
	{
		GetTagContent getContent = new GetTagContent();
		LinkedList<String> XMLFromEachBookHistory = 
				getContent.getTagContentsMultipleOccurrences(XMLWithBooksFromHistory, "book");
		return XMLFromEachBookHistory;
	}
	
	/**
	 * converts a XML with just one book history data in a usable BookHistoryData class
	 * @param XMLOfOneBookHistoryData XML of a single book history data
	 * @return usable BookHistoryData translated from XML
	 */
	private BookHistoryData getBookHistoryFromXML(String XMLOfOneBookHistoryData)
	{
		BookHistoryData bookHistoryData = new BookHistoryData();
		GetTagContent getContent = new GetTagContent();
		
		
		String bookTitle = getContent.getTagContent(XMLOfOneBookHistoryData, "booktitle");
		String mediumCoverAddress = 
				getContent.getTagContent(XMLOfOneBookHistoryData, "mediumcover");
		String bookStartDate = 
				getContent.getTagContent(XMLOfOneBookHistoryData, "started");
		String bookEndDate =
				getContent.getTagContent(XMLOfOneBookHistoryData, "completed");
		LinkedList<String> authors = getContent.getTagContentsMultipleOccurrences(XMLOfOneBookHistoryData, "author");
		
		bookHistoryData.setBookTitle(bookTitle);
		bookHistoryData.setMediumCover(mediumCoverAddress);
		bookHistoryData.setStartDate(bookStartDate);
		bookHistoryData.setEndDate(bookEndDate);
		bookHistoryData.setBookAuthors(authors);
		
		return bookHistoryData;
	}
	
	private static String reformatUsernameToQuery(String username)
	{
		String userNameToQuery = reformatUsernameToRevishSpecialUsers(username);
		if(userNameToQuery == null)
		{
			userNameToQuery ="";
			for(int i = 0; i < username.length(); i++)
			{
				char usernameChar = username.charAt(i);
				if(usernameChar != '.' && usernameChar != ' ')
				{
					userNameToQuery = userNameToQuery + usernameChar;
				}
			}
			//System.out.println("username to query=" + userNameToQuery);
		}
		
		return userNameToQuery;
		
	}
	
	/**
	 * revish's special users have a different user name, so we must
	 * convert these names so that we can use them normally in our search criteria.
	 * if the user name passed on this parameter is not a special user, this
	 * method returns null.
	 * @param username name of a user
	 * @return user name reformatted to special user or null if user is not special.
	 */
	public static String reformatUsernameToRevishSpecialUsers(String username)
	{
		if(username.compareToIgnoreCase("A. Bowdoin Van Riper") == 0)
		{
			return "abvr";
		}
		else if(username.compareToIgnoreCase("Jack Pickard") == 0)
		{
			return "JackP";
		}
		else if(username.compareToIgnoreCase("Johnnie Walker") == 0)
		{
			return "mrwalker";
		}
		else if(username.compareToIgnoreCase("Blair Millen") == 0)
		{
			return "Blair";
		}
		else if(username.compareToIgnoreCase("Dan Eastwell") == 0)
		{
			return "maskingtape";
		}
		else if(username.compareToIgnoreCase("Sara") == 0)
		{
			return "mutebutton";
		}
		else if(username.compareToIgnoreCase("Sarah Walker") == 0)
		{
			return "bluecat";
		}
		else if(username.compareToIgnoreCase("Dan Smith") == 0)
		{
			return "DanSmithAuthor";
		}
		else if(username.compareToIgnoreCase("Dan Smith") == 0)
		{
			return "DanSmithAuthor";
		}
		else if(username.compareToIgnoreCase("Kate Bolin") == 0)
		{
			return "katemonkey";
		}
		else if(username.compareToIgnoreCase("Susanna") == 0)
		{
			return "pebaline";
		}
		else if(username.compareToIgnoreCase("Tyler Schlagheck") == 0)
		{
			return "tks12dapro";
		}
		else if(username.compareToIgnoreCase("Rob") == 0)
		{
			return "ryal001";
		}
		else if(username.compareToIgnoreCase("Yvonne Pierre") == 0)
		{
			return "ypierre";
		}
		else if(username.compareToIgnoreCase("Elizabeth") == 0)
		{
			return "titania86";
		}
		else if(username.compareToIgnoreCase("marisa") == 0)
		{
			return "meduarte";
		}
		else if(username.compareToIgnoreCase("K.O'Keefe") == 0)
		{
			return "darkelf105";
		}
		else if(username.compareToIgnoreCase("Koty Onoabhagbe") == 0)
		{
			return "Koty1";
		}
		else if(username.compareToIgnoreCase("Daniel Farrey") == 0)
		{
			return "DRF73688";
		}
		else if(username.compareToIgnoreCase("Woo Eun Jung") == 0)
		{
			return "Jung";
		}
		else if(username.compareToIgnoreCase("Tara") == 0)
		{
			return "ptero27";
		}
		else if(username.compareToIgnoreCase("Mary Morgan") == 0)
		{
			return "freeradical";
		}
		else if(username.compareToIgnoreCase("Laurel") == 0)
		{
			return "laurelrobinson";
		}
		else if(username.compareToIgnoreCase("Stephanie M.") == 0)
		{
			return "saturnine13";
		}
		else if(username.compareToIgnoreCase("Leonard Driscoll") == 0)
		{
			return "speakbitterness";
		}
		else if(username.compareToIgnoreCase("Robert A. Boyd") == 0)
		{
			return "TheWrittenWyrd";
		}
		else if(username.compareToIgnoreCase("Wheldon Curzon-Hobson") == 0)
		{
			return "wheldon";
		}
		else if(username.compareToIgnoreCase("Geoff Oldham") == 0)
		{
			return "GeoffO";
		}
		else if(username.compareToIgnoreCase("Andr&eacute; John Haddad0") == 0)
		{
			return "AndreJohnHaddad";
		}
		else if(username.compareToIgnoreCase("Dan Champion") == 0)
		{
			return "danchamp";
		}
		else if(username.compareToIgnoreCase("Paul Kane") == 0)
		{
			return "Paul";
		}
		else if(username.compareToIgnoreCase("Emily") == 0)
		{
			return "devilyn";
		}
		else if(username.compareToIgnoreCase("Hayley Stiles") == 0)
		{
			return "Ikkaii";
		}
		else
		{
			return null;//no, not a special user
		}
	}





	
	

}
